﻿using Unity.Entities;
using Unity.Mathematics;
using Unity.Rendering;
using Unity.Jobs;
using Jinndev.Rendering2D;

namespace Jinndev.Tile2D {

    /// <summary>
    /// 按图集序列帧顺序和帧率计算TilingOffset<br/>
    /// 如果是动态序列，会根据帧率配置自动变换帧<br/>
    /// 如果是静态序列，可以在外部修改序列索引<br/>
    /// </summary>
    [UpdateAfter(typeof(CustomCullingSystem))]
    [UpdateBefore(typeof(CustomRenderSystem))]
    [UpdateBefore(typeof(TilingOffsetSystem))]
    public class SequenceFrameSystem : JobComponentSystem {

        protected override JobHandle OnUpdate(JobHandle inputDeps) {
            float deltaTime = Time.DeltaTime;

            inputDeps = Entities.WithNone<DisableRendering>().ForEach((ref DynamicBuffer<SequenceBuffer> sequenceBuffer, ref SequenceFrame sequenceFrame, ref AtlasTilingOffset atlasTilingOffset) => {
                if (!sequenceBuffer.IsCreated || sequenceFrame.sequenceIndex >= sequenceBuffer.Length) {
                    return;
                }

                // sequenceIndex如果改变，则需要更新
                if (sequenceFrame.sequenceIndex != sequenceFrame.lastSequenceIndex) {
                    sequenceFrame.dirty = true;
                }

                // 得到当前sequence
                Sequence sequence = sequenceBuffer[sequenceFrame.sequenceIndex].sequence;

                // 计算整数帧
                int frame;
                if (sequenceFrame.floor) {
                    frame = (int)math.floor(sequenceFrame.frame) % sequence.frames;
                }
                else {
                    frame = (int)math.ceil(sequenceFrame.frame) % sequence.frames;
                }

                // 如果帧数改变，则需要更新
                if (frame != sequenceFrame.lastFrame) {
                    sequenceFrame.dirty = true;
                }

                // 更新
                if (sequenceFrame.dirty) {
                    float4 tilingOffset;
                    if (sequenceFrame.reverse) {
                        tilingOffset = TileUtil.GetSequenceTilingOffset(sequence, sequenceFrame.dimension, sequenceFrame.anchor, sequenceFrame.direction, sequence.frames - 1 - frame);
                    }
                    else {
                        tilingOffset = TileUtil.GetSequenceTilingOffset(sequence, sequenceFrame.dimension, sequenceFrame.anchor, sequenceFrame.direction, frame);
                    }
                    atlasTilingOffset.Apply(tilingOffset);
                    sequenceFrame.dirty = false;
                }
                
                // 帧数播放
                if (sequenceFrame.play && sequence.fps != 0) {
                    sequenceFrame.frame += sequence.fps * deltaTime;
                    if (sequenceFrame.loop) {
                        sequenceFrame.frame %= sequence.frames;
                    }
                    else if (sequenceFrame.frame >= sequence.frames - 1) {
                        // 停在最后一帧
                        sequenceFrame.frame = sequence.frames - 1;
                        sequenceFrame.play = false;
                    }
                }
                else if(sequenceFrame.resetWhenStop) {
                    sequenceFrame.frame = 0;
                }

                // 记录状态
                sequenceFrame.lastFrame = frame;
                sequenceFrame.lastSequenceIndex = sequenceFrame.sequenceIndex;

            }).Schedule(inputDeps);

            inputDeps.Complete();
            return inputDeps;
        }

        


    }

}
